/*
 *  AudioStreamPlayer.h
 *  SoundController0002
 *
 *  Created by jiro on 10/07/04.
 *  Copyright 2010 jiro music. All rights reserved.
 *
 */

#pragma once

#include "AudioUnitPlayer.h"
#include "AudioStream.h"

namespace sc
{
	template< class AudioData >
	class AudioStreamPlayer : public AudioUnitPlayer
	{
	private:
		enum 
		{
			Buffer_Size = 2048,
		};

	private:

		std::vector< AudioStream< AudioData >* > audioStreams;

	public:

		AudioStreamPlayer()
		  : AudioUnitPlayer( AudioStreamPlayer::RenderCallback )
		{}

		void LoadStream( const std::vector< const AudioStream< AudioData >* >& streamers )
		{
			audioStreams = streamers;
		}

		void Play( double time )
		{
			size_t count = audioStreams.size();
			for ( size_t i = 0; i < count; i++ )
			{
				audioStreams[ i ]->StartStreaming( time );
			}

			AudioUnitPlayer::Play( time );
		}

		void Skip( double time )
		{}
		
		void Pause()
		{
			AudioUnitPlayer::Pause();
		}

		void Stop()
		{
			AudioUnitPlayer::Stop();
		}
		
		bool IsEnd() const
		{
			size_t count = audioStreams.size();
			for ( size_t i = 0; i < count; i++ )
			{
				if ( ! audioStreams[ i ]->IsStreamingEnd() )
				{
					return false;
				}
			}
			return true;
		}

		static OSStatus RenderCallback( 
			void* inRefCon,
			AudioUnitRenderActionFlags* ioActionFlag,
			const AudioTimeStamp* inTimeStamp,
			UInt32 inBusNumber,
			UInt32 inNumberFrames,
			AudioBufferList* ioData )
		{
			AudioStreamPlayer* player = (AudioStreamPlayer*) inRefCon;
			if ( player->IsEnd() )
			{
				player->Stop();
				return noErr;
			}
			
			int channelCount = ioData->mNumberBuffers;
			for ( int i = 0; i < inNumberFrames; i++ )
			{
				for ( int channelIndex = 0; channelIndex < channelCount; channelIndex++ )
				{
					float* dataPtr = static_cast< float* >( ioData->mBuffers[ channelIndex ].mData );
					*dataPtr = player->audioStreams[ channelIndex ]->Stream();
					dataPtr++;
				}
			}
			return noErr;
		}

	};
	
	typedef AudioStreamPlayer< float > AudioStreamPlayer32;
}